<template>
  <div class="inputType">
    <!-- 文本框 -->
    <el-input
      v-if="type === 'text' || (type === 'other' && filterModule)"
      v-model="value"
      :disabled="disabled"
      clearable
      :maxlength="inputMaxLength ? inputMaxLength : Infinity"
      placeholder="请输入内容"
      @blur="querySearch"
      @clear="querySearch"
      @keyup.enter.native="querySearch"
    ></el-input>
    <!-- 多个文本 -->
    <MoreInput
      :onlyReade="onlyReade"
      :group.sync="value"
      :field="field"
      :disabled="disabled"
      v-else-if="type === 'other'"
    ></MoreInput>
    <!-- 多行文本框 -->
    <el-input
      v-if="type === 'multi-text'"
      type="textarea"
      :rows="2"
      :maxlength="inputMaxLength ? inputMaxLength : Infinity"
      v-model="value"
      :disabled="disabled"
      @blur="querySearch"
      placeholder="请输入内容"
    ></el-input>
    <!-- 单选 -->
    <m7Select
      v-if="type === 'radio'"
      filterable
      clearable
      v-model="value"
      size="mini"
      :disabled="disabled"
      :options="data"
      :defaultProps="{ value: 'key', label: 'value' }"
      placeholder="请选择"
      style="width: 100%"
      @change="querySearch"
    >
    </m7Select>
    <!-- <el-select
      v-if="type === 'radio'"
      v-model="value"
      filterable
      clearable
      :disabled="disabled"
      placeholder="请选择"
      style="width: 100%"
      @change="querySearch"
    >
      <el-option
        v-for="item in data"
        :key="item.key"
        :label="item.value"
        :value="item.key"
      >
      </el-option>
    </el-select> -->
    <!-- 多选 -->
    <m7Select
      v-if="type === 'dropdown'"
      filterable
      clearable
      multiple
      collapse-tags
      v-model="value"
      size="mini"
      :disabled="disabled"
      :options="data"
      :defaultProps="{ value: 'key', label: 'value' }"
      placeholder="请选择"
      style="width: 100%"
      @change="querySearch"
    >
    </m7Select>
    <!-- <el-select
      v-if="type === 'dropdown'"
      v-model="value"
      filterable
      :disabled="disabled"
      placeholder="请选择"
      style="width: 100%"
      multiple
      collapse-tags
      clearable
      @change="querySearch"
    >
      <el-option
        v-for="item in data"
        :key="item.key"
        :label="item.value"
        :value="item.key"
      >
      </el-option>
    </el-select> -->
    <!-- 复选框 -->
    <el-checkbox-group
      v-if="type === 'checkbox'"
      v-model="value"
      :disabled="disabled"
      @change="querySearch"
    >
      <el-checkbox v-for="item in data" :key="item.key" :label="item.key">{{
        item.value
      }}</el-checkbox>
    </el-checkbox-group>
    <!-- 数字 && 条件选择介于 -->
    <span v-if="type === 'number' && operator === 'between'">
      <el-input-number
        v-model="value"
        :disabled="disabled"
        style="width: 49%"
        :controls="true"
        size="small"
        @blur="querySearch"
      >
      </el-input-number>
      <el-input-number
        v-model="value2"
        :disabled="disabled"
        style="width: 49%; margin-left: 2%"
        :controls="true"
        size="small"
        @blur="querySearch"
      >
      </el-input-number>
    </span>
    <!-- 数字 -->
    <el-input-number
      v-else-if="type === 'number'"
      v-model="value"
      :disabled="disabled"
      style="width: 100%"
      :controls="true"
      size="small"
      :min="1"
      :max="maxNum ? maxNum : Infinity"
      @blur="querySearch"
    >
    </el-input-number>
    <!-- 级联 -->
    <el-cascader
      ref="cascader"
      style="width: 100%"
      size="small"
      v-if="type === 'cascade'"
      v-model="value"
      :disabled="disabled"
      :options="data"
      filterable
      clearable
      :props="{
        multiple: searchShow,
        checkStrictly: !Boolean(cascaderAllChoose),
        label: isArea ? 'fullname' : 'value',
        value: isArea ? 'id' : 'key',
      }"
      :collapse-tags="true"
      placeholder="请选择"
      @change="querySearch"
      @visible-change="clearChoose"
    >
    </el-cascader>
    <span v-if="type === 'date' && operator === 'between'">
      <!-- 日期 -->
      <el-date-picker
        style="width: 49%"
        v-model="value"
        :disabled="disabled"
        type="date"
        value-format="yyyy-MM-dd"
        placeholder="选择日期"
        @change="querySearch"
      >
      </el-date-picker>
      <el-date-picker
        style="width: 49%; margin-left: 2%"
        v-model="value2"
        :disabled="disabled"
        type="date"
        value-format="yyyy-MM-dd"
        placeholder="选择日期"
        @change="querySearch"
      >
      </el-date-picker>
    </span>
    <!-- 日期 -->
    <el-date-picker
      style="width: 100%"
      v-else-if="type === 'date'"
      v-model="value"
      :disabled="disabled"
      type="date"
      value-format="yyyy-MM-dd"
      placeholder="选择日期"
      @change="querySearch"
    >
    </el-date-picker>
    <span v-if="type === 'datetime' && operator === 'between'">
      <el-date-picker
        style="width: 49%"
        v-model="value"
        :disabled="disabled"
        type="datetime"
        value-format="yyyy-MM-dd HH:mm:ss"
        placeholder="选择日期时间"
        @change="querySearch"
      >
      </el-date-picker>
      <el-date-picker
        style="width: 49%; margin-left: 2%"
        v-model="value2"
        :disabled="disabled"
        type="datetime"
        value-format="yyyy-MM-dd HH:mm:ss"
        placeholder="选择日期时间"
        @change="querySearch"
      >
      </el-date-picker>
    </span>
    <!-- 时间 -->
    <el-date-picker
      style="width: 100%"
      v-else-if="type === 'datetime'"
      v-model="value"
      :disabled="disabled"
      type="datetime"
      value-format="yyyy-MM-dd HH:mm:ss"
      placeholder="选择日期时间"
      @change="querySearch"
    >
    </el-date-picker>
    <!-- 日期范围 -->
    <el-date-picker
      style="width: 100%"
      v-if="type === 'date-range'"
      v-model="value"
      :disabled="disabled"
      type="daterange"
      value-format="yyyy-MM-dd"
      range-separator="-"
      start-placeholder="开始日期"
      end-placeholder="结束日期"
      @change="querySearch"
    >
    </el-date-picker>
    <!-- 时间范围 -->
    <el-date-picker
      style="width: 100%"
      v-if="type === 'datetime-range'"
      v-model="value"
      :disabled="disabled"
      value-format="yyyy-MM-dd HH:mm:ss"
      type="datetimerange"
      range-separator="-"
      start-placeholder="开始日期"
      end-placeholder="结束日期"
      @change="querySearch"
    >
    </el-date-picker>
    <el-upload
      class="upLoad"
      v-if="type === 'attachment'"
      action=""
      accept=".xls, .xlsx, .doc, .docx, .pdf, .png, .jpeg, .jpg, .pptx, .txt, .zip, .rar, .mp4, .mp3, .mav"
      :limit="3"
      :disabled="isShowProgress || attachsObj.length >= 4"
      :show-file-list="false"
      :on-success="uploadSuccess"
      :onProgress="onFileProgress"
      :before-upload="beforeUpload"
      :http-request="uploadRequest"
    >
      <el-button type="primary" size="mini">上传附件</el-button>
    </el-upload>
    <div style="margin-top: 5px">
      <draggable
        v-model="attachsObj"
        handle=".attachMove"
        animation="150"
        ghostClass="dragClass"
      >
        <div
          class="attachsItem"
          v-for="(item, index) in attachsObj"
          :key="item.id"
        >
          <span class="attachMove" title="拖动排序"
            ><i
              style="font-size: 12px"
              class="V7_iconfont V7_iconV7tubiao_yidong"
            ></i
          ></span>
          <a :href="item.id" target="_blank" download>{{ item.name }}</a>
          <span class="attachDel" @click="attachDelFun(item, index)"
            ><i
              style="font-size: 12px"
              class="V7_iconfont V7_iconV7tubiao_guanbi"
            ></i
          ></span>
          <span title="预览" v-preview.delete="[item.name, item.id]"
            ><i
              style="font-size: 14px; margin-left: 8px; cursor: pointer"
              class="V7_iconfont V7_iconV7tubiao_kejian"
            ></i
          ></span>
        </div>
      </draggable>
    </div>
    <el-progress
      v-if="isShowProgress"
      :text-inside="false"
      :percentage="progress"
      :color="colors"
    ></el-progress>
  </div>
</template>

<script lang="ts">
/**
 * 根据不同的数据类型渲染不同的输入组件
 * @Prop propData
 * {
 *  type: 类型,
 *  data: 输入组件的数据
 * }
 * @Prop propValue 原始值，注意使用sync双向绑定
 * input 单行文本
 * textarea 多行文本
 * dropdown 单选
 * checkbox 多选 没有使用复选框模式，看后面要求修改
 * number 数字
 * cascader 级联选择
 * date 日期
 * datetime 日期时间
 * daterange 日期范围
 * datetimerange 日期时间范围
 * moreinput 可添加多个的输入框
 * @Prop filterModule 是否是检索模块
 * @Prop operator 当选选择的条件
 */
import { Component, Vue, Prop, Watch, Ref } from 'vue-property-decorator'
import MoreInput from './moreInput.vue'
import { uploadQiniu } from '@/utils/upload'
import draggable from 'vuedraggable'
@Component({
  name: 'InputType',
  components: {
    MoreInput,
    draggable
  }
})
export default class InputType extends Vue {
  [x: string]: any
  @Ref() private readonly moreInput
  @Prop() private propValue: any
  @Prop() private propData: any
  @Prop() private filterModule!: boolean
  @Prop() private operator!: string
  @Prop() private onlyReade
  @Prop({ default: false }) private searchShow
  private type = 'text'
  private value: any = ''
  private value2: any = ''
  private field: any = ''
  private data: any = []
  private disabled: boolean = false
  private fileName: any = ''
  private isShowProgress: boolean = false
  private progress = 0
  private attachsObj: any = []
  private isArea: boolean = false
  private inputMaxLength: number = 0
  private maxNum: number = Infinity
  private cascaderAllChoose: boolean = false
  private colors: any = [
    { color: '#008CEE', percentage: 90 },
    { color: '#67C23A', percentage: 100 }
  ]

  private gender (val: any) { // 性别
    switch (val) {
      case 'F':
        return '女'
      case 'M':
        return '男'
      case 'N':
        return '保密'
    }
  }

  private clearChoose (val) {
    if (val) {
      this.$nextTick(() => {
        // (this.$refs.cascader as any).$refs.panel.clearCheckedNodes(); // 清空级联选择器选中状态
        (this.$refs.cascader as any).$refs.panel.activePath = []; // 清除高亮
        (this.$refs.cascader as any).$refs.panel.syncActivePath(); // 初始化（只展示一级节点）
      })
    }
  }

  private removeItem (val) {
    console.log(val, 77677)
  }

  private querySearch () {
    setTimeout(() => {
      this.$emit('querySearch')
    })
  }

  private uploadRequest (request: any) { // 七牛上传
    uploadQiniu({ type: 'common', fileName: this.fileName }, request)
  }

  private beforeUpload (file: any) { // 上传前验证文件合法性
    this.fileName = file.name.replace(/\s/g, '')
    if (file.size / 1024 / 1024 > 20) {
      this.$message({ message: '附件大小不能超过20M', type: 'error' })
      return false
    } else {
      this.isShowProgress = true
    }
  }

  private uploadSuccess (data: any) { // 上传成功
    const initConfig = this.$store.state.common.initConfig
    this.attachsObj.push({ id: initConfig && data.key ? `${initConfig.qiniuDomainMap.common}/${data.key}` : '', name: this.fileName })
    this.isShowProgress = false
    this.progress = 0
    this.value = this.attachsObj
  }

  private onFileProgress (data: any) {
    this.progress = Math.ceil(data.percent)
  }

  private attachDelFun (item: any, index: number) {
    this.attachsObj.splice(index, 1)
    this.value = this.attachsObj
  }

  // 初始化数据
  private setData (data) {
    this.type = data.type
    this.field = data.field
    if (['name'].includes(this.field)) {
      this.inputMaxLength = 20
    } else if (['serviceAccount', 'servicePassword'].includes(this.field)) {
      this.inputMaxLength = 50
    } else if (['memo'].includes(this.field)) {
      this.inputMaxLength = 200
    }
    if (['age'].includes(this.field)) {
      this.maxNum = 999
    }
    this.isArea = Boolean(data.field === 'region')
    this.disabled = (this.filterModule || !data.editable) ? false : data.editable // 检索模块，不用受配置限制设置为disabled
    if (['cascade'].includes(this.type)) {
      this.data = data.options ? data.options.children : []
      this.cascaderAllChoose = data.options && data.options.fillLevel
    } else if (['checkbox', 'radio', 'dropdown'].includes(this.type)) {
      this.data = data.choices || []
    }
    if (this.type === 'radio' && data.field === 'gender') { // 性别的要单独处理
      this.data.map(item => {
        item.value = this.gender(item.key)
      })
    }
  }

  private setValue (val: any) {
    this.$set(this, 'value', val)
    if (['datetime-range', 'date-range', 'checkbox'].includes(this.type) && !this.value) {
      this.value = []
    }
    if (['attachment'].includes(this.type)) {
      if (this.value && this.value.length) {
        this.attachsObj = this.value
      } else if (this.value && !this.value.length) { // value = []
        this.attachsObj = []
      } else { // value不存在
        this.attachsObj = []
        this.value = []
      }
    }
    if (['other'].includes(this.type) && !this.value && !this.filterModule) { // 是多个文本 && 没有值 && 不是过滤器模块
      this.value = [{}]
    }
    if (['age'].includes(this.field) && !this.value) {
      this.value = undefined
    }
  }

  // 监听选中值变化
  @Watch('propData', { immediate: true, deep: true })
  private updataData (val) {
    if (val) {
      this.setData(val)
    }
  }

  // 监听选中值变化
  @Watch('propValue', { immediate: true, deep: true })
  private updataPropValue (val) {
    if (['number', 'date', 'datetime'].includes(this.type) && this.operator === 'between' && typeof val === 'object') {
      this.value2 = val[1] || ''
      this.setValue(val[0] || '')
    } else {
      this.setValue(val)
    }
  }

  // 监听选中值变化
  @Watch('value', { immediate: true, deep: true })
  private updataValue (val) {
    if (['number', 'date', 'datetime'].includes(this.type) && this.operator === 'between') { // 数字，日期，日期时间 介于类型的，要绑定2个值，自己重新组装
      this.$emit('updatePropValue', { value: val, value2: this.value2, operator: 'between', type: 'number' }, this.field)
    } else {
      this.$emit('updatePropValue', val, this.field)
    }
  }

  @Watch('value2', { immediate: true, deep: true })
  private updataValue2 (val) {
    if (['number', 'date', 'datetime'].includes(this.type) && this.operator === 'between') {
      this.$emit('updatePropValue', { value: this.value, value2: val, operator: 'between', type: 'number' }, this.field)
    }
  }
}
</script>

<style lang="stylus" scoped>
.inputType
  flex 1
  /deep/ .el-range__icon
    line-height 24px
  /deep/ .el-range-separator
    line-height 24px
  /deep/ .el-range__close-icon
    line-height 24px
>>> .el-progress__text
  color #ccc
  font-size 12px !important
.dragClass
  opacity 0
.addAttachs
  padding 8px 12px
  font-size 12px
  line-height 12px
  border 1px solid #E7E9ED
  border-radius 4px
  .addBtn
    color #008BEE
  .size
    color #767E91
.attachsItem
  padding 8px 9px
  font-size 12px
  line-height 12px
  background #F1F8FD
  border-radius 4px
  color #008BEE
  display inline-block
  margin 0px 10px 10px 0px
  .attachMove
    margin-right 10px
    cursor move
  .attachDel
    margin-left 10px
    cursor pointer
</style>
